package ihm.views.main;

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.LayoutManager;

import ihm.controllers.ATKcontroller;
import ihm.models.ATKlistener;
import ihm.models.events.CharacterChangedEvent;
import ihm.models.events.EquipmentChangedEvent;
import ihm.models.events.ItemTypeChangedEvent;
import ihm.models.events.LanguageChangedEvent;
import ihm.models.events.QueryChangedEvent;
import ihm.models.events.StatChangedEvent;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;

import characters.Characters;
import equipments.Items;
import equipments.enumeration.AccessoriesSlots;
import equipments.enumeration.ArmorSlots;

import systems.exceptions.equipments.ItemIsNullException;
import systems.languages.MultiLanguages;

/**
 * EquipmentPanel is part of the MainFrame. Then, this class implements
 * ATKsubview and require a controller to get some changement.
 * This part of the view require to get update when the language and the 
 * characted used changed. 
 * At last, this view is based on Swing Technologies and more specificaly, the
 * JTree and JScrollPane components.
 * @author Baptiste Legrand & Benjamin Orman
 * @version 2.0
 */
public class EquipmentPanel extends JPanel implements ATKlistener
{
  private static final long serialVersionUID = 1L;
  /** Panel stuff **/
  // The LayoutManager
  private LayoutManager gridBagLayout = new GridBagLayout();
  // The Constraint to apply for a component
  private GridBagConstraints  gbc = new GridBagConstraints();
  // The JLabel used to display the picture of the character's classe
  private JLabel classePicture= new JLabel();
  // A copy of the Character stores in the model.
  private Characters character;
  
  /** Character's Labels **/
  private JLabel characterNameLabel= new JLabel();
  private JLabel characterLevelLabel= new JLabel();
  private JLabel factionLabel= new JLabel();
  private JLabel classeLabel;
  //Main Hand
  private JLabel mainHandLabel= new JLabel();
  //Off Hand
  private JLabel offHandLabel= new JLabel();
  //Armor Items
  private JLabel armorLabel= new JLabel();
  //Accessory Items
  private JLabel accessoriesLabel= new JLabel();
  /**
   * Constructor creating a new instance of the EquipmentPanel.This constructor
   * do a local copie of the controller and the character used in the model. 
   * Since the EquipmentPanel extends a Swing technologie, this constructor 
   * also initialize
   * @param controller - The controller which will be used to notify the change.
   */
  public EquipmentPanel(ATKcontroller controller)
  {
    super();
    
    this.character = controller.getModel().getCharacter();
    
    this.setLayout(gridBagLayout);
    
    this.setBackground(Color.white);
    this.setBorder(BorderFactory.createLineBorder(Color.gray));

    this.updateLabel();

    this.buildPanel();
  }

  private void updateLabel()
  {
    String begin = "<html><b>";
    String end = "</b></html>";
    mainHandLabel.setText(begin+MultiLanguages.getProperties("equipment.MainHand.label")+end);
    offHandLabel.setText(begin+MultiLanguages.getProperties("equipment.OffHand.label")+end);
    armorLabel.setText(begin+MultiLanguages.getProperties("equipment.Armor.label")+end);
    accessoriesLabel.setText(begin+MultiLanguages.getProperties("equipment.Accessories.label")+end);
  }

  private void buildPanel()
  {
    //First we start to put the classe picture
    this.buildClassePict();
    //Next : the character's info (lvl, name, faction, classe)
    this.buildCharacterLabels();
    //JSep
    this.buildJSeparator(0,2);
    //Next : Main hand
    this.buildMainHand();
    //JSep
    this.buildJSeparator(0,5);
    //Next : Off hand
    this.buildOffHand();
    //JSep
    this.buildJSeparator(0,8);
    //Next : Armor
    this.buildArmor();
    //JSep
    this.buildJSeparator(0,15);
    //Next : Accessories
    this.buildAccessories();
  }

  private void buildClassePict()
  {
    classePicture = new JLabel(new ImageIcon(character.getClasse().getImagePath()));
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridheight = 2; //Occupera 2 lignes verticalements
    gbc.gridwidth = 1; //Occupera 1 ligne horizontale
    //Marges
    //gbc.insets = new Insets(10,10,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.CENTER;
    //Ajout de l'image au panel
    this.add(classePicture, gbc);
  }

  private void buildCharacterLabels()
  {
    String level = MultiLanguages.getProperties("equipment.Level.label");
    characterLevelLabel= new JLabel(level+" "+String.valueOf(character.getLevel())+" ");
    gbc.gridx = 1;
    gbc.gridy = 0;
    gbc.gridheight = 1; //Occupera 1 ligne verticalement
    gbc.gridwidth = GridBagConstraints.RELATIVE;//Avant derniere place sur la ligne
    //Marges
    //gbc.insets = new Insets(10,0,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.LINE_START;
    //Ajout au panel
    this.add(characterLevelLabel, gbc);
    
    characterNameLabel = new JLabel(character.getName());
    gbc.gridx = 2;
    gbc.gridy = 0;
    gbc.gridwidth = GridBagConstraints.REMAINDER;//Derniere place sur la ligne
    gbc.gridheight = 1; //Occupera 1 ligne verticalement
    //Marges
    //gbc.insets = new Insets(10,0,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.LINE_START;
    //Ajout au panel
    this.add(characterNameLabel, gbc);
    
    factionLabel = new JLabel(
        MultiLanguages.getProperties(
            character.getFaction().getMultiLanguageName()
        )
    );
    gbc.gridx = 1;
    gbc.gridy = 1;
    gbc.gridwidth = GridBagConstraints.RELATIVE;//Avant derniere place sur la ligne
    gbc.gridheight = 1; //Occupera 1 ligne verticalement

    //Marges
    //gbc.insets = new Insets(10,0,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.LINE_START;
    //Ajout au panel
    this.add(factionLabel, gbc);
    
    classeLabel = new JLabel(MultiLanguages.getProperties(character.getClasse().getMultiLanguageName()));
    gbc.gridx = 2;
    gbc.gridy = 1;
    gbc.gridwidth = GridBagConstraints.REMAINDER;//Derniere place sur la ligne
    gbc.gridheight = 1; //Occupera 1 ligne verticalement

    //Marges
    //gbc.insets = new Insets(10,0,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.LINE_START;
    //Ajout au panel
    this.add(classeLabel, gbc);
  }
  
  private void buildMainHand()
  {
    gbc.gridx = 0;
    gbc.gridy = 3;
    gbc.gridwidth = GridBagConstraints.REMAINDER;//Derniere place sur la ligne
    //Marges
    //gbc.insets = new Insets(10,0,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.LINE_START;
    //Ajout au panel
    this.add(mainHandLabel, gbc);
    try {
      this.buildItemRow(0,4,character.getEquipment().getMainHandItem());
    } catch (ItemIsNullException e) {
      this.buildEmptyItem(0,4);
    }
  }
  private void buildOffHand()
  {
    gbc.gridx = 0;
    gbc.gridy = 6;
    gbc.gridwidth = GridBagConstraints.REMAINDER;//Derniere place sur la ligne
    //Marges
    //gbc.insets = new Insets(10,0,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.LINE_START;
    //Ajout au panel
    this.add(offHandLabel, gbc);
    try {
      this.buildItemRow(0,7,character.getEquipment().getOffHandItem());
    } catch (ItemIsNullException e) {
      this.buildEmptyItem(0,7);
    }
  }
  
  private void buildArmor()
  {
    gbc.gridx = 0;
    gbc.gridy = 9;
    gbc.gridwidth = GridBagConstraints.REMAINDER;//Derniere place sur la ligne
    //Marges
    //gbc.insets = new Insets(10,0,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.LINE_START;
    //Ajout au panel
    this.add(armorLabel, gbc);
    int gridy = 10;
    for(ArmorSlots armor : ArmorSlots.values())
    {
      try {
        this.buildItemRow(0,gridy,character.getEquipment().getArmorPart(armor));
      } catch (ItemIsNullException e) {
        this.buildEmptyItem(0,gridy);
      }
      gridy ++;
    }
  }
  
  private void buildAccessories()
  {
    gbc.gridx = 0;
    gbc.gridy = 16;
    gbc.gridwidth = GridBagConstraints.REMAINDER;//Derniere place sur la ligne
    //Marges
    //gbc.insets = new Insets(10,0,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.LINE_START;
    //Ajout au panel
    this.add(accessoriesLabel, gbc);
    int gridy = 17;
    for(AccessoriesSlots accessorie : AccessoriesSlots.values())
    {
      //System.out.println("Accessoire pour le slot "+accessorie);
      try {
        this.buildItemRow(0,gridy,character.getEquipment().getAccessory(accessorie));
        //System.out.println("--> non vide");
      } catch (ItemIsNullException e) {
        //System.out.println("--> vide");
        this.buildEmptyItem(0,gridy);
      }
      gridy ++;
    }
  }
  
  private void buildItemRow(int gridx, int gridy, Items item)
  {
    gbc.gridx = gridx;
    gbc.gridy = gridy;
    gbc.gridwidth = GridBagConstraints.REMAINDER;//Derniere place sur la ligne
    //Marges
    //gbc.insets = new Insets(10,0,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.LINE_START;
    //Update du nom de lobjet
    item.updateName();
    //Ajout au panel
    this.add(new JLabel(item.getName()), gbc);
  }
  
  
  private void buildEmptyItem(int gridx, int gridy)
  {
    gbc.gridx = gridx;
    gbc.gridy = gridy;
    gbc.gridwidth = GridBagConstraints.REMAINDER;//Derniere place sur la ligne
    //Marges
    //gbc.insets = new Insets(10,0,10,10);
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.LINE_START;
    //Ajout au panel
    this.add(new JLabel("<html><i>"+MultiLanguages.getProperties("equipment.Empty.label")+"</i></html>"), gbc);
  }
  
  private void buildJSeparator(int gridx, int gridy)
  {
    gbc.gridx = gridx;
    gbc.gridy = gridy;
    gbc.gridwidth = GridBagConstraints.REMAINDER;//Derniere place sur la ligne
    //Point d'ancrage � l'interieur des cellules
    gbc.anchor = GridBagConstraints.CENTER;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    //Ajout au panel
    this.add(new JSeparator(), gbc);
  }

  @Override
  public void CharacterChanged(CharacterChangedEvent event) {
    this.removeAll();
    this.character = event.getNewCharacter(); 
    buildPanel();
    this.repaint();
    this.revalidate(); 
  }

  @Override
  public void EquipmentChanged(EquipmentChangedEvent event) {
    this.removeAll();
    this.character = event.getNewEquipment().getCharacter();
    buildPanel();
    this.repaint();
    this.revalidate();    
  }

  @Override
  public void ItemTypeChanged(ItemTypeChangedEvent event) {
    //Nothing to do
  }

  @Override
  public void LanguageChanged(LanguageChangedEvent event) {
    this.removeAll();
    buildPanel();
    this.updateLabel();
    this.repaint();
    this.revalidate();
  }

  @Override
  public void QueryChanged(QueryChangedEvent event) {
    //Nothing to treat.    
  }

  @Override
  public void StatChanged(StatChangedEvent event) {
    //Nothing to treat.    
  }
}
